/*
 * Copyright (C) 2012 CyberAgent
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cn.jarlen.photoedit.filter.base;

import java.nio.IntBuffer;

import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.hardware.Camera.Size;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.util.Log;

public class OpenGlUtils
{
	public static final int NO_TEXTURE = -1;

	public static int loadTexture(final Bitmap img, final int usedTexId)
	{
		return loadTexture(img, usedTexId, true);
	}

	public static int loadTexture(final Bitmap img, final int usedTexId,
			final boolean recycle)
	{
		int textures[] = new int[1];
		if (usedTexId == NO_TEXTURE)
		{
			GLES20.glGenTextures(1, textures, 0);
			GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
			GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
					GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
			GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
					GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
			GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
					GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
			GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
					GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

			GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, img, 0);
		} else
		{
			GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, usedTexId);
			GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, img);
			textures[0] = usedTexId;
		}
		if (recycle)
		{
			img.recycle();
		}
		return textures[0];
	}

	public static int loadTexture(final IntBuffer data, final Size size,
			final int usedTexId)
	{
		int textures[] = new int[1];
		if (usedTexId == NO_TEXTURE)
		{
			GLES20.glGenTextures(1, textures, 0);
			GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
			GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
					GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
			GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
					GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
			GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
					GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
			GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
					GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
			GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA,
					size.width, size.height, 0, GLES20.GL_RGBA,
					GLES20.GL_UNSIGNED_BYTE, data);
		} else
		{
			GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, usedTexId);
			GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, size.width,
					size.height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, data);
			textures[0] = usedTexId;
		}
		return textures[0];
	}

	public static int loadTextureAsBitmap(final IntBuffer data,
			final Size size, final int usedTexId)
	{
		Bitmap bitmap = Bitmap.createBitmap(data.array(), size.width,
				size.height, Config.ARGB_8888);
		return loadTexture(bitmap, usedTexId);
	}

	public static int loadShader(final String strSource, final int iType)
	{
		int[] compiled = new int[1];
		int iShader = GLES20.glCreateShader(iType);
		GLES20.glShaderSource(iShader, strSource);
		GLES20.glCompileShader(iShader);
		GLES20.glGetShaderiv(iShader, GLES20.GL_COMPILE_STATUS, compiled, 0);
		if (compiled[0] == 0)
		{
			Log.d("Load Shader Failed",
					"Compilation\n" + GLES20.glGetShaderInfoLog(iShader));
			return 0;
		}
		return iShader;
	}

	public static int loadProgram(final String strVSource,
			final String strFSource)
	{
		int iVShader;
		int iFShader;
		int iProgId;
		int[] link = new int[1];
		iVShader = loadShader(strVSource, GLES20.GL_VERTEX_SHADER);
		if (iVShader == 0)
		{
			Log.d("Load Program", "Vertex Shader Failed");
			return 0;
		}
		iFShader = loadShader(strFSource, GLES20.GL_FRAGMENT_SHADER);
		if (iFShader == 0)
		{
			Log.d("Load Program", "Fragment Shader Failed");
			return 0;
		}

		iProgId = GLES20.glCreateProgram();

		GLES20.glAttachShader(iProgId, iVShader);
		GLES20.glAttachShader(iProgId, iFShader);

		GLES20.glLinkProgram(iProgId);

		GLES20.glGetProgramiv(iProgId, GLES20.GL_LINK_STATUS, link, 0);
		if (link[0] <= 0)
		{
			Log.d("Load Program", "Linking Failed");
			return 0;
		}
		GLES20.glDeleteShader(iVShader);
		GLES20.glDeleteShader(iFShader);
		return iProgId;
	}

	public static float rnd(final float min, final float max)
	{
		float fRandNum = (float) Math.random();
		return min + (max - min) * fRandNum;
	}
}
